package cn.com.ethos.search.query;

import java.io.IOException;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;


public class SearchFacade implements ISearcher{
	
	private Logger logger = Logger.getLogger(this.getClass());
	
	private IndexReader reader;
	private Analyzer analyzer;
	
	public Analyzer getAnalyzer() {
		return this.analyzer;
	}

	public void setAnalyzer(Analyzer analyzer) {
		this.analyzer = analyzer;
	}

	public SearchFacade(Directory dir,Analyzer analyzer) throws IOException {
		this.reader   = IndexReader.open(dir);
		this.analyzer = analyzer;
	}
	
	public SearchFacade(String path,Analyzer analyzer) throws IOException {
		this(FSDirectory.getDirectory(path),analyzer);
	}
	
	public SearchFacade(Directory dir) throws IOException{
		this(dir,new StandardAnalyzer());
	}
	
	public SearchFacade(String path) throws IOException {
		this(path,new StandardAnalyzer());
	}
	
	public Hits search(String query) 
				throws ParseException,IOException {
		IndexSearcher is = new IndexSearcher(reader);
		QueryParser parser = new QueryParser("content",analyzer);
		//parser.setDefaultOperator(QueryParser.AND_OPERATOR);
		
		Query q = parser.parse(query);
		logger.info("\tthe query is:" + q.toString());
		return is.search(q);
	}
	
	public ResultResponse search(String query,int size,int page) 
				throws ParseException,IOException,InvalidParameterException {
		
		if(page < 1) {
			throw new InvalidParameterException("the page should not less than 1");
		}
		
		Hits hits = this.search(query);
		
		int total = hits.length();
		int start = Math.min(size*(page-1),total);
		int end   = Math.min(start+size,total);
		
		List<Document> list = new ArrayList<Document>();
		for(;start<end;start++) {
			list.add(hits.doc(start));
		}
		return new ResultResponse(list,hits.length());
	}

	@Override
	public Response search(Request request) throws Exception{
		return this.search(request.getQuery(),request.getSize(),request.getPage());
	}
	
	
	
}
